home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume8 / vn / part03 < prev    next >
Encoding:
Internet Message Format  |  1987-02-16  |  47.8 KB

  1. Subject:  v08i066:  The VN news reader, Part03/03
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: rtech!rtech!bobm (Bob Mcqueer)
  6. Mod.sources: Volume 8, Issue 66
  7. Archive-name: vn/Part03
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # If all goes well, you will see the message "End of archive 3 (of 3)."
  13. # Contents:  vn.c vn.man
  14. # Wrapped by rs@mirror on Tue Feb 17 12:10:41 1987
  15. PATH=/bin:/usr/bin:/usr/ucb; export PATH
  16. echo shar: extracting "'vn.c'" '(25993 characters)'
  17. if test -f 'vn.c' ; then 
  18.   echo shar: will not over-write existing file "'vn.c'"
  19. else
  20. sed 's/^X//' >vn.c <<'@//E*O*F vn.c//'
  21. X/*
  22. Xvn news reader for visual page oriented display of news
  23. Xaimed at scanning large numbers of articles.
  24. X
  25. XOriginal program by Bob McQueer in several versions 1983-1986.  Released
  26. Xinto the public domain in 1986.  While no copyright notice appears, the
  27. Xoriginal author asks that a history of changes crediting the proper people
  28. Xbe maintained.
  29. X
  30. XBob McQueer
  31. X{amdahl, sun, mtxinu, hoptoad, cpsc6a}!rtech!bobm
  32. X
  33. XHistory:
  34. X
  35. X    (bobm@rtech) 5/86 - first "public" version
  36. X
  37. X    (bobm@rtech) 12/86 - version incorporates:
  38. X
  39. X        bug fixes:
  40. X            str_store NULL string bug
  41. X            not picking up first article in newsgroup
  42. X            RESTART terminal reset for exit to editor.
  43. X            skip whitespace in "empty" digest lines while unpacking
  44. X            DISTRIBUTION line in followups.
  45. X            :100%: prompt on last line in reader.
  46. X            interpretation of multiple negations -w -t options.
  47. X
  48. X            Many thanks to several people who noted the first
  49. X            two bugs as well as fixes.
  50. X
  51. X            Thank you to Karl Williamson for helpful information
  52. X            tracking down the "concept terminal" bug (RESTART).
  53. X
  54. X        SYSV ifdef's adapted from those done by Larry Tepper
  55. X        at ATT Denver - sent in by Karl Williamson, drutx!khw.
  56. X        Many people submitted SYSV ifdef's - thank you all.
  57. X
  58. X        print capability from reader from Karl Williamson,
  59. X        drutx!khw
  60. X
  61. X        Changes to use alternate header lines for mail, from changes
  62. X        by Andy Marrinson, andy@icom.UUCP (ihnp4!icom!andy).  Ifdef'ed
  63. X        to allow local configuration (bobm@rtech).
  64. X
  65. X        "author_copy" file for followups, prevention of multiple
  66. X        "re: "'s, insert blank line and original author line
  67. X        before excerpted text from Andy Marrinson, andy@icom.UUCP
  68. X
  69. X        Search string capability in reader, from Lawrie Brown,
  70. X        seismo!munnari!cdsadfa.oz!lpb (Australia).  Somewhat
  71. X        modified by interaction with the :100%: bug.
  72. X
  73. X        Arrow key support, adapted from changes by Lawrie Brown.
  74. X        Modified to simply not allow control keys for arrows (allowing
  75. X        SOME controls is too prone to problems, esp. with .vnkey), and
  76. X        to allow the PAGEARROW ifdef (bobm@rtech)
  77. X
  78. X        prevention of followups to "mod" and "announce", from
  79. X        Lawrie Brown.
  80. X
  81. X        OLDRC ifdef adapted from changes by Lawrie Brown.  ADDRMUNGE
  82. X        added to allow OZ domain addressing changes from Australia
  83. X        to be grafted back in, and provide a hook for anybody else
  84. X        wanting to do something similar.
  85. X
  86. X        Bob McQueer, bobm@rtech:
  87. X
  88. X            a menu selection from the % command to jump to
  89. X            a new newsgroup
  90. X
  91. X            linked list on hash table - no longer a compiled
  92. X            in limit for number of newsgroups
  93. X
  94. X            .vnkey keystroke mapping file.
  95. X
  96. X            options to get the % command list on entry, and to
  97. X            change how unsubscribed groups are handled for updates.
  98. X
  99. X            allow configurable use of vs / ve pair for terminal
  100. X            handling.
  101. X
  102. XKnown bugs:
  103. X
  104. X    non-erasure of stuff on prompt line when the new
  105. X    string includes an escape sequence (like PS1 maybe)
  106. X    because it doesn't realize that the escape sequence
  107. X    won't overprint the existing stuff
  108. X
  109. X    control-w and update on exit may not update pages which have been
  110. X    scanned in funny orders by jumping into the middle of groups
  111. X
  112. X    inaccurate numbers on '%' command results - reflect ranges, not
  113. X    actual numbers of articles.
  114. X
  115. X    no arrow keys recognized which don't begin with <escape>
  116. X
  117. X    doesn't know about the version 2.11 'm' in active list, or
  118. X    use the 'y' / 'n' either.
  119. X
  120. X    crash due to embedding $\(\) type substring specifiers in regular
  121. X    expressions.  Obscure and hard to fix in a proper and portable way.
  122. X*/
  123. X#include <stdio.h>
  124. X#include <setjmp.h>
  125. X#include "config.h"
  126. X#include "tty.h"
  127. X#include "vn.h"
  128. X
  129. X/* UNIX error number */
  130. Xextern int errno;
  131. X
  132. Xextern NODE **Newsorder;
  133. Xextern char Erasekey, Killkey;
  134. Xextern int Rot;
  135. Xextern char *Ps1,*Printer;
  136. Xextern char *Orgdir,*Savefile,*Savedir;
  137. Xextern int Ncount, Cur_page, Lrec, L_allow, C_allow;
  138. Xextern int Headflag;
  139. Xextern PAGE Page;
  140. Xextern int Digest;
  141. Xextern char *No_msg;
  142. Xextern char *Hdon_msg;
  143. Xextern char *Hdoff_msg;
  144. Xextern char *Roton_msg;
  145. Xextern char *Rotoff_msg;
  146. Xextern char Cxitop[], Cxptoi[];
  147. X
  148. Xextern char *Aformat;
  149. X
  150. Xextern char *Contstr;
  151. X
  152. Xextern char *Kl,*Kr,*Ku,*Kd;
  153. X
  154. Xextern int Nounsub, Listfirst;
  155. X
  156. Xstatic int C_info;
  157. Xstatic int Dskip, Drec;
  158. X
  159. Xstatic char *Unsub_msg = "Unsubscribed";
  160. Xstatic char *Egroup_msg = "Entire newsgroup";
  161. X
  162. X/*
  163. X    Help message table.  Character for command, plus its help
  164. X    message.  Table order is order of presentation to user.
  165. X*/
  166. Xstatic struct HELPTAB
  167. X{
  168. X    char cmd, *msg;
  169. X    int dig;
  170. X    char *amsg;
  171. X} 
  172. XHelptab [] =
  173. X{
  174. X    { QUIT, "quit", 1, NULL},
  175. X    { UP, "(or up arrow) move up [number of lines]", 1, NULL},
  176. X    { DOWN, "(or down arrow) move down [number of lines]", 1, NULL},
  177. X#ifdef PAGEARROW
  178. X    { BACK, "(or left arrow) previous page [number of pages]", 1, NULL},
  179. X    { FORWARD, "(or right arrow) next page [number of pages]", 1, NULL},
  180. X#else
  181. X    { BACK, "previous page [number of pages]", 1, NULL},
  182. X    { FORWARD, "next page [number of pages]", 1, NULL},
  183. X#endif
  184. X    { DIGEST, "unpack digest", 1, "exit digest"},
  185. X    { READ, "read article [number of articles]", 1, NULL},
  186. X    { ALTREAD, "read article (alternate 'r')", 1, NULL},
  187. X    { READALL, "read all articles on page", 1, NULL},
  188. X    { READSTRING, "specify articles to read", 1, NULL},
  189. X    { SAVE, "save or pipe article [number of articles]", 1, NULL},
  190. X    { SAVEALL, "save or pipe all articles on page", 1, NULL},
  191. X    { SAVESTRING, "specify articles to save", 1, NULL},
  192. X    { ALTSAVE, "specify articles to save (alternate ctl-s)", 1, NULL},
  193. X    { PRINT, "print article [number of articles]", 1, NULL},
  194. X    { PRINTALL, "print all article on page", 1, NULL},
  195. X    { PRINTSTRING, "specify articles to print", 1, NULL},
  196. X    { UPDATE, "update .newsrc status to cursor", 0, NULL},
  197. X    { UPALL, "update .newsrc status for whole newsgroup", 0, NULL},
  198. X    { UPSEEN, "update .newsrc status for all pages displayed", 0, NULL},
  199. X    { ORGGRP, "recover original .newsrc status for newsgroup", 0, NULL},
  200. X    { ORGSTAT, "recover all original .newsrc status", 0, NULL},
  201. X    { SSTAT, "display count of groups and pages - shown and total", 0, NULL},
  202. X    { GRPLIST, "list newsgroups with new article, updated counts", 0, NULL},
  203. X    { NEWGROUP, "specify newsgroup to display and/or resubscribe to", 1, NULL},
  204. X    { UNSUBSCRIBE, "unsubscribe from group", 0, NULL},
  205. X    { MARK, "mark/unmark article [number of articles]", 1, NULL},
  206. X    { ART_MARK, "mark/unmark article [number of articles]", 1, NULL},
  207. X    { UNMARK, "erase marks on articles", 1, NULL},
  208. X    { HEADTOG, "toggle flag for display of headers when reading", 1, NULL},
  209. X    { SETROT, "toggle rotation for reading", 1, NULL},
  210. X    { REDRAW, "redraw screen", 1, NULL},
  211. X    { UNESC, "escape to UNIX to execute a command", 1, NULL},
  212. X    { HELP, "show this help menu", 1, NULL}
  213. X};
  214. X
  215. Xmain(argc,argv)
  216. Xint argc;
  217. Xchar **argv;
  218. X{
  219. X    /*
  220. X        initialize environment variables,
  221. X        scan .newsrc file, using any command line options present.
  222. X     */
  223. X    term_set (START);
  224. X    envir_set ();
  225. X    sig_set (BRK_IN);
  226. X
  227. X    scan_newsrc (argc-1,argv+1);
  228. X    tty_set (BACKSTOP);
  229. X
  230. X    if (Lrec >= 0)
  231. X        session ();
  232. X    else
  233. X    {
  234. X        new_groups ();
  235. X        fprintf (stderr,"\nNo News\n");
  236. X    }
  237. X
  238. X    tty_set (COOKED);
  239. X    wr_newsrc ();
  240. X    term_set (STOP);
  241. X}
  242. X
  243. X/*
  244. X    main session handler processing input commands
  245. X    locals:
  246. X        count - count attached to command
  247. X        highrec - highest line on current page
  248. X        crec - current line
  249. X
  250. X    NOTE: this is where a setjmp call is made to set the break reentry
  251. X        location.  Keep the possible user states in mind.
  252. X*/
  253. Xsession ()
  254. X{
  255. X    char alist [RECLEN], c;
  256. X    int newg, i, j, count, highrec, crec;
  257. X    jmp_buf brkbuf;
  258. X
  259. X    tty_set (RAWMODE);
  260. X    newg = new_groups();
  261. X    find_page (0);
  262. X    Digest = 0;
  263. X
  264. X    /* reentry point for break from within session interaction */
  265. X    setjmp (brkbuf);
  266. X    sig_set (BRK_SESS,brkbuf);
  267. X    Headflag = FALSE;
  268. X    Rot = 0;
  269. X
  270. X    /* done this way so that user gets "really quit?" break treatment */
  271. X    if (newg > 0)
  272. X    {
  273. X        printf ("\n%s",Contstr);
  274. X        getnoctl();
  275. X        newg = 0;
  276. X    }
  277. X
  278. X    /* list preview option - clear after first time for long jumps */
  279. X    if (Listfirst)
  280. X    {
  281. X        /* tot_list settings will be overwritten in this case */
  282. X        tot_list(&crec,&highrec);
  283. X        Listfirst = 0;
  284. X    }
  285. X
  286. X    /* if breaking from a digest, recover original page */
  287. X    if (Digest)
  288. X    {
  289. X        find_page(Cur_page);
  290. X        Digest = 0;
  291. X    }
  292. X    show ();
  293. X    crec = RECBIAS;
  294. X    highrec = Page.h.artnum + RECBIAS;
  295. X    term_set (MOVE,0,crec);
  296. X
  297. X    /*
  298. X        handle commands until QUIT, update global/local status
  299. X        and display for each.
  300. X     */
  301. X    for (count = getkey(&c); c != QUIT; count = getkey(&c))
  302. X    {
  303. X        for (i=0; i < (j = sizeof(Helptab)/sizeof(struct HELPTAB)); ++i)
  304. X            if (Helptab[i].cmd == c)
  305. X                break;
  306. X
  307. X        if (i >= j || (Digest && !Helptab[i].dig))
  308. X        {
  309. X            preinfo (UDKFORM,Cxptoi[HELP]);
  310. X            term_set (MOVE, 0, crec);
  311. X            continue;
  312. X        }
  313. X
  314. X        switch (c)
  315. X        {
  316. X        case HEADTOG:
  317. X            if (Headflag)
  318. X            {
  319. X                Headflag = FALSE;
  320. X                prinfo (Hdoff_msg);
  321. X            }
  322. X            else
  323. X            {
  324. X                Headflag = TRUE;
  325. X                prinfo (Hdon_msg);
  326. X            }
  327. X            term_set (MOVE,0,crec);
  328. X            break;
  329. X        case SETROT:
  330. X            if (Rot == 0)
  331. X            {
  332. X                Rot = 13;
  333. X                prinfo (Roton_msg);
  334. X            }
  335. X            else
  336. X            {
  337. X                Rot = 0;
  338. X                prinfo (Rotoff_msg);
  339. X            }
  340. X            term_set (MOVE,0,crec);
  341. X            break;
  342. X        case SSTAT:
  343. X            count_msg ();
  344. X            term_set (MOVE,0,crec);
  345. X            break;
  346. X        case GRPLIST:
  347. X            tot_list (&crec,&highrec);
  348. X            show();
  349. X            term_set (MOVE,0,crec);
  350. X            break;
  351. X        case REDRAW:
  352. X            show();
  353. X            term_set (MOVE,0,crec);
  354. X            break;
  355. X        case UNSUBSCRIBE:
  356. X            (Page.h.group)->state &= ~FLG_SUB;
  357. X            wr_newsrc ();
  358. X            prinfo (Unsub_msg);
  359. X            term_set (MOVE,0,crec);
  360. X            break;
  361. X
  362. X        case UPDATE:
  363. X            (Page.h.group)->rdnum = Page.b[crec-RECBIAS].art_id;
  364. X            wr_show ();
  365. X            wr_newsrc();
  366. X            term_set (MOVE,0,crec);
  367. X            break;
  368. X        case UPALL:
  369. X            (Page.h.group)->rdnum = (Page.h.group)->art;
  370. X            wr_newsrc();
  371. X            wr_show();
  372. X            prinfo (Egroup_msg);
  373. X            term_set (MOVE,0,crec);
  374. X            break;
  375. X        case ORGGRP:
  376. X            (Page.h.group)->rdnum = (Page.h.group)->orgrd;
  377. X            wr_newsrc();
  378. X            wr_show();
  379. X            prinfo (Egroup_msg);
  380. X            term_set (MOVE,0,crec);
  381. X            break;
  382. X        case UPSEEN:
  383. X            up_seen();
  384. X            prinfo ("All pages displayed to this point updated");
  385. X            wr_show();
  386. X            wr_newsrc();
  387. X            term_set (MOVE,0,crec);
  388. X            break;
  389. X        case ORGSTAT:
  390. X            for (i = 0; i < Ncount; ++i)
  391. X                (Newsorder[i])->rdnum = (Newsorder[i])->orgrd;
  392. X            prinfo ("Original data recovered");
  393. X            wr_show();
  394. X            wr_newsrc();
  395. X            term_set (MOVE,0,crec);
  396. X            break;
  397. X        case UP:
  398. X            if (crec != RECBIAS)
  399. X            {
  400. X                crec -= count;
  401. X                if (crec < RECBIAS)
  402. X                    crec = RECBIAS;
  403. X                term_set (MOVE, 0, crec);
  404. X            }
  405. X            else
  406. X                putchar ('\07');
  407. X            break;
  408. X        case DOWN:
  409. X            if (crec < (highrec - 1))
  410. X            {
  411. X                crec += count;
  412. X                if (crec >= highrec)
  413. X                    crec = highrec - 1;
  414. X                term_set (MOVE, 0, crec);
  415. X            }
  416. X            else
  417. X                putchar ('\07');
  418. X            break;
  419. X        case MARK:
  420. X        case ART_MARK:
  421. X            count += crec - 1;
  422. X            if (count >= highrec)
  423. X                count = highrec - 1;
  424. X            for (i=crec; i <= count; ++i)
  425. X            {
  426. X                if (Page.b[i-RECBIAS].art_mark != ART_MARK)
  427. X                    Page.b[i-RECBIAS].art_mark = ART_MARK;
  428. X                else
  429. X                    Page.b[i-RECBIAS].art_mark = ' ';
  430. X                if (i != crec)
  431. X                    term_set (MOVE, 0, i);
  432. X                printf ("%c\010",Page.b[i-RECBIAS].art_mark);
  433. X            }
  434. X            if (count != crec)
  435. X                term_set (MOVE, 0, crec);
  436. X            write_page ();
  437. X            break;
  438. X        case UNMARK:
  439. X            for (i=0; i < Page.h.artnum; ++i)
  440. X            {
  441. X                if (Page.b[i].art_mark == ART_MARK)
  442. X                {
  443. X                    Page.b[i].art_mark = ' ';
  444. X                    term_set (MOVE, 0, i+RECBIAS);
  445. X                    putchar (' ');
  446. X                }
  447. X            }
  448. X            term_set (MOVE, 0, crec);
  449. X            write_page ();
  450. X            break;
  451. X        case BACK:
  452. X            count *= -1;    /* fall through */
  453. X        case FORWARD:
  454. X            if (forward (count, &crec, &highrec) >= 0)
  455. X                show();
  456. X            else
  457. X                preinfo ("No more pages");
  458. X            term_set (MOVE,0,crec);
  459. X            break;
  460. X        case DIGEST:
  461. X            if (Digest)
  462. X            {
  463. X                Digest = 0;
  464. X                find_page (Cur_page);
  465. X                show();
  466. X                crec = Drec + RECBIAS + 1;
  467. X                highrec = Page.h.artnum + RECBIAS;
  468. X                if (crec >= highrec)
  469. X                    crec = highrec - 1;
  470. X                term_set (MOVE,0,crec);
  471. X                break;
  472. X            }
  473. X            Dskip = count - 1;
  474. X            Drec = crec - RECBIAS;
  475. X            if (digest_page(Drec,Dskip) >= 0)
  476. X            {
  477. X                show();
  478. X                crec = RECBIAS;
  479. X                highrec = Page.h.artnum + RECBIAS;
  480. X                term_set (MOVE,0,crec);
  481. X                break;
  482. X            }
  483. X            Digest = 0;
  484. X            preinfo ("Can't unpack the article");
  485. X            term_set (MOVE,0,crec);
  486. X            break;
  487. X        case NEWGROUP:
  488. X            if ((i = spec_group()) < 0)
  489. X            {
  490. X                term_set (MOVE,0,crec);
  491. X                break;
  492. X            }
  493. X            Digest = 0;
  494. X            show();
  495. X            crec = RECBIAS;
  496. X            highrec = Page.h.artnum + RECBIAS;
  497. X            term_set (MOVE,0,crec);
  498. X            break;
  499. X
  500. X        case SAVE:
  501. X            genlist (alist,crec-RECBIAS,count);
  502. X            savestr (alist);
  503. X            term_set (MOVE,0,crec);
  504. X            break;
  505. X        case SAVEALL:
  506. X            genlist (alist,0,L_allow);
  507. X            savestr (alist);
  508. X            term_set (MOVE,0,crec);
  509. X            break;
  510. X        case SAVESTRING:
  511. X        case ALTSAVE:
  512. X            userlist (alist);
  513. X            savestr (alist);
  514. X            term_set (MOVE,0,crec);
  515. X            break;
  516. X        case READ:
  517. X        case ALTREAD:
  518. X            genlist (alist,crec-RECBIAS,count);
  519. X            readstr (alist,&crec,&highrec,count);
  520. X            break;
  521. X        case READALL:
  522. X            genlist (alist,0,L_allow);
  523. X            readstr (alist,&crec,&highrec,0);
  524. X            break;
  525. X        case READSTRING:
  526. X            userlist (alist);
  527. X            readstr (alist,&crec,&highrec,0);
  528. X            break;
  529. X        case PRINT:
  530. X            genlist (alist,crec-RECBIAS,count);
  531. X            printstr (alist);
  532. X            term_set (MOVE,0,crec);
  533. X            break;
  534. X        case PRINTALL:
  535. X            genlist (alist,0,L_allow);
  536. X            printstr (alist);
  537. X            term_set (MOVE, 0, crec);
  538. X            break;
  539. X        case PRINTSTRING:
  540. X            userlist (alist);
  541. X            printstr (alist);
  542. X            term_set (MOVE, 0, crec);
  543. X            break;
  544. X
  545. X        case HELP:
  546. X            help ();
  547. X            show ();
  548. X            term_set (MOVE, 0, crec);
  549. X            break;
  550. X        case UNESC:
  551. X            user_str (alist,Ps1,1);
  552. X            term_set (ERASE);
  553. X            fflush (stdout);
  554. X            tty_set (SAVEMODE);
  555. X            if (chdir(Orgdir) < 0)
  556. X                printf ("change to original directory, %s, failed",Orgdir);
  557. X            else
  558. X            {
  559. X                system (alist);
  560. X                tty_set (RESTORE);
  561. X                term_set (RESTART);
  562. X            }
  563. X            printf (Contstr);
  564. X            getnoctl ();
  565. X            cd_group ();
  566. X            show ();
  567. X            term_set (MOVE, 0, crec);
  568. X            break;
  569. X        default:
  570. X            printex ("Unhandled key: %c", c);
  571. X            break;
  572. X        }
  573. X    }
  574. X
  575. X    Digest = 0;
  576. X    for (i=0; i < Ncount; ++i)
  577. X    {
  578. X        if ((Newsorder[i])->rdnum < (Newsorder[i])->pgrd)
  579. X            break;
  580. X    }
  581. X    if (i < Ncount)
  582. X    {
  583. X        user_str (alist,"Some displayed pages not updated - update ? ",1);
  584. X        if (alist[0] == 'y')
  585. X            up_seen();
  586. X    }
  587. X    sig_set (BRK_OUT);
  588. X}
  589. X
  590. X/*
  591. X** update status of Newsgroups to all seen pages
  592. X*/
  593. Xup_seen()
  594. X{
  595. X    int i;
  596. X
  597. X    for (i = 0; i < Ncount; ++i)
  598. X    {
  599. X        if (Nounsub && ((Newsorder[i])->state & FLG_SUB) == 0)
  600. X        {
  601. X            (Newsorder[i])->rdnum = (Newsorder[i])->art;
  602. X            continue;
  603. X        }
  604. X        if ((Newsorder[i])->rdnum < (Newsorder[i])->pgrd)
  605. X            (Newsorder[i])->rdnum = (Newsorder[i])->pgrd;
  606. X    }
  607. X}
  608. X
  609. X/*
  610. X    count_msg displays count information
  611. X*/
  612. Xcount_msg ()
  613. X{
  614. X    int i, gpnum, gscan, gpage;
  615. X    unsigned long mask;
  616. X    gpnum = 1;
  617. X    for (gscan = gpage = i = 0; i<Ncount; ++i)
  618. X    {
  619. X        if (((Newsorder[i])->state & FLG_PAGE) != 0)
  620. X        {
  621. X            if (((Newsorder[i])->pnum + (Newsorder[i])->pages - 1) < Cur_page)
  622. X                ++gpnum;
  623. X            ++gpage;
  624. X            for (mask=1; mask != 0L; mask <<= 1)
  625. X                if (((Newsorder[i])->pgshwn & mask) != 0L)
  626. X                    ++gscan;
  627. X        }
  628. X    }
  629. X    prinfo (CFORMAT,Cur_page+1,Lrec+1,gscan,gpnum,gpage);
  630. X}
  631. X
  632. X/*
  633. X    forward utility handles paging to allow it to happen globally.
  634. X    (from readstr, for instance)
  635. X*/
  636. Xforward (count, crec, highrec)
  637. Xint count, *crec, *highrec;
  638. X{
  639. X    if (!Digest)
  640. X    {
  641. X        if ((count < 0 && Cur_page <= 0) || (count > 0 && Cur_page >= Lrec))
  642. X            return (-1);
  643. X        Cur_page += count;
  644. X        if (Cur_page < 0)
  645. X            Cur_page = 0;
  646. X        if (Cur_page > Lrec)
  647. X            Cur_page = Lrec;
  648. X        find_page (Cur_page);
  649. X        *crec = RECBIAS;
  650. X        *highrec = Page.h.artnum + RECBIAS;
  651. X        return (0);
  652. X    }
  653. X    /*
  654. X    ** in digests, paging past the end of the digest returns to
  655. X    ** page extracted from.
  656. X    */
  657. X    if (Dskip > 0 && (Dskip + count*L_allow) < 0)
  658. X        Dskip = 0;
  659. X    else
  660. X        Dskip += count * L_allow;
  661. X    find_page (Cur_page);
  662. X    if (Dskip >= 0)
  663. X    {
  664. X        if (digest_page(Drec,Dskip) >= 0)
  665. X        {
  666. X            *crec = RECBIAS;
  667. X            *highrec = Page.h.artnum + RECBIAS;
  668. X            return (0);
  669. X        }
  670. X    }
  671. X    Digest = 0;
  672. X    *crec = Drec + RECBIAS + 1;
  673. X    *highrec = Page.h.artnum + RECBIAS;
  674. X    if (*crec >= *highrec)
  675. X        *crec = *highrec - 1;
  676. X    return (0);
  677. X}
  678. X
  679. X/*
  680. X    error/abnormal condition cleanup and abort routine
  681. X    pass stack to printf
  682. X*/
  683. Xprintex (s,a,b,c,d,e,f)
  684. Xchar *s;
  685. Xlong a,b,c,d,e,f;
  686. X{
  687. X    static int topflag=0;
  688. X    if (topflag == 0)
  689. X    {
  690. X        ++topflag;
  691. X        term_set (STOP);
  692. X        tty_set (COOKED);
  693. X        fflush (stdout);
  694. X        fprintf (stderr,s,a,b,c,d,e,f);
  695. X        fprintf (stderr," (error code %d)\n",errno);
  696. X        exit (1);
  697. X    }
  698. X    else
  699. X        fprintf (stderr,s,a,b,c,d,e,f);
  700. X}
  701. X
  702. X/*
  703. X    getkey obtains user keystroke with count from leading
  704. X    numerics, if any.  Picks up arrow key sequences and maps
  705. X    them to other keys.  Also translates character through
  706. X    Cxitop array since this routine is only used in session
  707. X    loop.  Saves untranslating arrow keys.
  708. X*/
  709. Xgetkey (c)
  710. Xchar *c;
  711. X{
  712. X    int i, j;
  713. X    static char    ckseq[32];
  714. X
  715. X    /* Check for leading count */
  716. X    for (i = 0; (*c = getchar() & 0x7f) >= '0' && *c <= '9'; i = i * 10 + *c - '0')
  717. X        ;
  718. X
  719. X    /* @#$!!! flakey front ends that won't map newlines in raw mode */
  720. X    if (*c == '\012' || *c == '\015')
  721. X        *c = '\n';
  722. X
  723. X    /* @#$!!! flakey terminals which send control sequences for cursors! */
  724. X    if( *c == '\033' )
  725. X    {
  726. X        /*
  727. X        ** Check if part of cursor key input sequence
  728. X        ** (pitch unknown escape sequences)
  729. X        */
  730. X        j = 0;
  731. X        ckseq[j] = *c; ckseq[j+1] = '\0';
  732. X        while(*c == Ku[j] || *c == Kd[j] || *c == Kl[j] || *c == Kr[j])
  733. X        {
  734. X            if( strcmp(ckseq, Ku) == 0 ) { *c = UP; break; }
  735. X            if( strcmp(ckseq, Kd) == 0 ) { *c = DOWN; break; }
  736. X#ifdef PAGEARROW
  737. X            if( strcmp(ckseq, Kl) == 0 ) { *c = BACK; break; }
  738. X            if( strcmp(ckseq, Kr) == 0 ) { *c = FORWARD; break; }
  739. X#else
  740. X            if( strcmp(ckseq, Kl) == 0 ) { *c = UP; break; }
  741. X            if( strcmp(ckseq, Kr) == 0 ) { *c = DOWN; break; }
  742. X#endif
  743. X            *c = (getchar() & 0x7f);
  744. X            ckseq[++j] = *c; ckseq[j+1] = '\0';
  745. X        }
  746. X    }
  747. X    else
  748. X        *c = Cxitop[*c];
  749. X
  750. X    if (i <= 0)
  751. X        i = 1;
  752. X    return (i);
  753. X}
  754. X
  755. X
  756. X/*
  757. X    get user key ignoring most controls
  758. X*/
  759. Xgetnoctl ()
  760. X{
  761. X    char c;
  762. X    while ((c = getchar() & 0x7f) < ' ' || c == '\177')
  763. X    {
  764. X        if (c == '\015' || c == '\012')
  765. X            c = '\n';
  766. X        if (c == '\n' || c == '\b' || c == '\t')
  767. X            return (c);
  768. X    }
  769. X    return ((int) c);
  770. X}
  771. X
  772. X/*
  773. X    generate list of articles on current page,
  774. X    count articles, starting with first.
  775. X*/
  776. Xgenlist (list,first,count)
  777. Xchar *list;
  778. Xint first,count;
  779. X{
  780. X    int i;
  781. X    for (i=first; i < Page.h.artnum && count > 0; ++i)
  782. X    {
  783. X        sprintf (list,"%d ",Page.b[i].art_id);
  784. X        list += strlen(list);
  785. X        --count;
  786. X    }
  787. X}
  788. X
  789. X/*
  790. X    send list of articles to printer
  791. X*/
  792. Xprintstr (s)
  793. Xchar *s;
  794. X{
  795. X    char *ptr, cmd [RECLEN], *strpbrk();
  796. X    prinfo ("preparing print command ....");
  797. X    for (ptr = s; (ptr = strpbrk(ptr, LIST_SEP)) != NULL; ++ptr)
  798. X        *ptr = ' ';
  799. X    while (*s == ' ')
  800. X        ++s;
  801. X    if (Digest)
  802. X        dig_list (s);
  803. X    if (*s != '\0')
  804. X    {
  805. X        sprintf (cmd,"%s %s 2>/dev/null",Printer,s);
  806. X        if (system (cmd) == 0)
  807. X            prinfo ("Sent to printer");
  808. X        else
  809. X            preinfo ("Print failed");
  810. X    }
  811. X    else
  812. X        preinfo (No_msg);
  813. X    if (Digest)
  814. X        dig_ulist (s);
  815. X}
  816. X
  817. X/*
  818. X    concatenate articles to save file with appropriate infoline messages.
  819. X    prompt for save file, giving default.  If save file begins with "|"
  820. X    handle as a filter to pipe to.  NOTE - every user specification of
  821. X    a new Savefile "loses" some storage, but it shouldn't be a very great
  822. X    amount.
  823. X*/
  824. Xsavestr (s)
  825. Xchar *s;
  826. X{
  827. X    char *ptr, cmd [RECLEN], newfile [MAX_C+1], prompt[MAX_C];
  828. X    char *strtok(), *strpbrk(), *str_store();
  829. X
  830. X    for (ptr = s; (ptr = strpbrk(ptr, LIST_SEP)) != NULL; ++ptr)
  831. X        *ptr = ' ';
  832. X    while (*s == ' ')
  833. X        ++s;
  834. X    if (Digest)
  835. X        dig_list (s);
  836. X    if (*s != '\0')
  837. X    {
  838. X        sprintf (prompt,SAVFORM,Savefile);
  839. X        user_str (newfile,prompt,1);
  840. X        ptr = newfile;
  841. X        if (*ptr == '|')
  842. X        {
  843. X            sprintf(cmd,"cat %s %s",s,ptr);
  844. X            term_set (ERASE);
  845. X            fflush (stdout);
  846. X            tty_set (SAVEMODE);
  847. X            system (cmd);
  848. X            tty_set (RESTORE);
  849. X            printf (Contstr);
  850. X            getnoctl ();
  851. X            show ();
  852. X        }
  853. X        else
  854. X        {
  855. X            prinfo ("saving .... ");
  856. X            if (*ptr == '\0')
  857. X                ptr = Savefile;
  858. X            else
  859. X                Savefile = str_store(ptr);
  860. X            if (*ptr != '/' && *ptr != '$')
  861. X                sprintf(cmd,"cat %s >>%s/%s 2>/dev/null",s,Savedir,ptr);
  862. X            else
  863. X                sprintf(cmd,"cat %s >>%s 2>/dev/null",s,ptr);
  864. X            if (system (cmd) == 0)
  865. X                prinfo ("Saved");
  866. X            else
  867. X                preinfo ("Could not append save file");
  868. X        }
  869. X    }
  870. X    else
  871. X        preinfo (No_msg);
  872. X    if (Digest)
  873. X        dig_ulist (s);
  874. X}
  875. X
  876. X/*
  877. X    basic page display routine.  erase screen and format current page
  878. X*/
  879. Xshow ()
  880. X{
  881. X    int i;
  882. X    unsigned long mask;
  883. X    char helpstr[40]; 
  884. X
  885. X    term_set (ERASE);
  886. X    C_info = 0;
  887. X    i = Cur_page - (Page.h.group)->pnum + 1;
  888. X    if (Digest)
  889. X        printf (DHFORMAT,Page.h.name);
  890. X    else
  891. X        printf (HFORMAT,Page.h.name,i,(Page.h.group)->pages);
  892. X
  893. X    mask = 1L << (i-1);
  894. X    (Page.h.group)->pgshwn |= mask;
  895. X    mask = 1;
  896. X    for (--i; i > 0 && (mask & (Page.h.group)->pgshwn) != 0 ; --i)
  897. X        mask <<= 1;
  898. X    if (i <= 0)
  899. X        (Page.h.group)->pgrd = Page.b[(Page.h.artnum)-1].art_id;
  900. X
  901. X    for (i=0; i < Page.h.artnum; ++i)
  902. X    {
  903. X        if (Digest)
  904. X        {
  905. X            printf(Aformat,Page.b[i].art_mark,ART_UNWRITTEN,Page.b[i].art_id);
  906. X            printf("%s",Page.b[i].art_t);
  907. X            continue;
  908. X        }
  909. X
  910. X        if ((Page.h.group)->rdnum >= Page.b[i].art_id)
  911. X            printf(Aformat,Page.b[i].art_mark,ART_WRITTEN,Page.b[i].art_id);
  912. X        else
  913. X            printf(Aformat,Page.b[i].art_mark,ART_UNWRITTEN,Page.b[i].art_id);
  914. X        printf("%s",Page.b[i].art_t);
  915. X    }
  916. X
  917. X    sprintf(helpstr,HELPFORM,Cxptoi[HELP]);
  918. X    if (!Digest && ((Page.h.group)->state & FLG_SUB) == 0)
  919. X        prinfo ("%s, %s",Unsub_msg,helpstr);
  920. X    else
  921. X        prinfo (helpstr);
  922. X}
  923. X
  924. X/*
  925. X    update written status marks on screen
  926. X*/
  927. Xwr_show ()
  928. X{
  929. X    int i,row;
  930. X    char c;
  931. X
  932. X    row = RECBIAS;
  933. X    for (i=0; i < Page.h.artnum; ++i)
  934. X    {
  935. X        term_set (MOVE,WRCOL,row);
  936. X        if ((Page.h.group)->rdnum >= Page.b[i].art_id)
  937. X            c = ART_WRITTEN;
  938. X        else
  939. X            c = ART_UNWRITTEN;
  940. X        printf("%c",c);
  941. X        ++row;
  942. X    }
  943. X}
  944. X
  945. X/*
  946. X    obtain user input of group name, becomes current page if valid.
  947. X    returns -1 or page number.  calling routine does the show, if needed
  948. X*/
  949. Xspec_group ()
  950. X{
  951. X    char nbuf [MAX_C + 1];
  952. X    NODE *p, *hashfind();
  953. X
  954. X    user_str(nbuf,"Newsgroup ? ",1);
  955. X
  956. X    if (*nbuf == '\0' || (p = hashfind(nbuf)) == NULL)
  957. X    {
  958. X        preinfo ("Not a newsgroup");
  959. X        return (-1);
  960. X    }
  961. X    if ((p->state & FLG_PAGE) == 0)
  962. X    {
  963. X        if ((p->state & FLG_SUB) == 0)
  964. X        {
  965. X            p->state |= FLG_SUB;
  966. X            wr_newsrc ();
  967. X            prinfo ("Not subscribed: resubscribed for next reading session");
  968. X        }
  969. X        else
  970. X            prinfo ("No news for that group");
  971. X        return (-1);
  972. X    }
  973. X    if ((p->state & FLG_SUB) == 0)
  974. X    {
  975. X        p->state |= FLG_SUB;
  976. X        wr_newsrc ();
  977. X    }
  978. X    find_page (p->pnum);
  979. X    return (p->pnum);
  980. X}
  981. X
  982. X/*
  983. X    obtain user input with prompt p.  Optionally on info line.
  984. X    handle erase and kill characters, suppresses leading
  985. X    white space.
  986. X*/
  987. Xuser_str (s,p,iline)
  988. Xchar *s;
  989. Xchar *p;
  990. Xint iline;
  991. X{
  992. X    int i,idx;
  993. X
  994. X    if (iline)
  995. X    {
  996. X        prinfo ("%s",p);
  997. X        idx = C_info;
  998. X    }
  999. X    else
  1000. X    {
  1001. X        printf ("%s",p);
  1002. X        idx = strlen(p);
  1003. X    }
  1004. X
  1005. X    for (i=0; idx < C_allow && (s[i] = getchar() & 0x7f) != '\012' && s[i] != '\015'; ++i)
  1006. X    {
  1007. X        if (s[i] == Erasekey)
  1008. X        {
  1009. X            if (i > 0)
  1010. X            {
  1011. X                term_set (RUBSEQ);
  1012. X                i -= 2;
  1013. X                --idx;
  1014. X            }
  1015. X            continue;
  1016. X        }
  1017. X        if (s[i] == Killkey)
  1018. X        {
  1019. X            prinfo ("%s",p);
  1020. X            i = -1;
  1021. X            continue;
  1022. X        }
  1023. X        if ((s[i] == ' ' || s[i] == '\t') && i == 0)
  1024. X        {
  1025. X            i = -1;
  1026. X            continue;
  1027. X        }
  1028. X        ++idx;
  1029. X        putchar (s[i]);
  1030. X    }
  1031. X
  1032. X    if (iline)
  1033. X        C_info = idx;
  1034. X
  1035. X    s[i] = '\0';
  1036. X}
  1037. X
  1038. X
  1039. X/*
  1040. X    print something on the information line,
  1041. X    clearing any characters not overprinted.
  1042. X    preinfo includes reverse video and a bell for error messages.
  1043. X*/
  1044. Xpreinfo (s,a,b,c,d,e,f)
  1045. X{
  1046. X    int l;
  1047. X    char buf[RECLEN];
  1048. X
  1049. X    term_set (MOVE,0,INFOLINE);
  1050. X    putchar ('\07');
  1051. X    term_set (ONREVERSE);
  1052. X    sprintf (buf,s,a,b,c,d,e,f);
  1053. X    printf (" %s ",buf);
  1054. X    term_set (OFFREVERSE);
  1055. X    l = strlen(buf) + 2;
  1056. X    if (l < C_info)
  1057. X        term_set (ZAP,l,C_info);
  1058. X    C_info = l;
  1059. X    fflush(stdout);
  1060. X}
  1061. X
  1062. Xprinfo (s,a,b,c,d,e,f)
  1063. Xchar *s;
  1064. Xlong a,b,c,d,e,f;
  1065. X{
  1066. X    int l;
  1067. X    char buf[RECLEN];
  1068. X    term_set (MOVE,0,INFOLINE);
  1069. X    sprintf (buf,s,a,b,c,d,e,f);
  1070. X    printf ("%s",buf);
  1071. X    l = strlen(buf);
  1072. X    if (l < C_info)
  1073. X        term_set (ZAP,l,C_info);
  1074. X    C_info = l;
  1075. X    fflush(stdout);
  1076. X}
  1077. X
  1078. X/*
  1079. X    help menu
  1080. X*/
  1081. Xhelp ()
  1082. X{
  1083. X    int i,lcount,lim; 
  1084. X    term_set (ERASE);
  1085. X    lim = L_allow + RECBIAS - 2;
  1086. X    printf("%s\n",HELP_HEAD);
  1087. X    lcount = HHLINES;
  1088. X    for (i=0; i < (sizeof(Helptab))/(sizeof(struct HELPTAB)); ++i)
  1089. X    {
  1090. X        if (Digest && !(Helptab[i].dig))
  1091. X            continue;
  1092. X        ++lcount;
  1093. X        if (Digest && Helptab[i].amsg != NULL)
  1094. X            h_print (Cxptoi[Helptab[i].cmd],Helptab[i].amsg);
  1095. X        else
  1096. X            h_print (Cxptoi[Helptab[i].cmd],Helptab[i].msg);
  1097. X        if (lcount >= lim)
  1098. X        {
  1099. X            printf ("\n%s",Contstr);
  1100. X            getnoctl ();
  1101. X            term_set (MOVE,0,lim+1);
  1102. X            term_set (ZAP,0,strlen(Contstr));
  1103. X            term_set (MOVE,0,lim-1);
  1104. X            putchar ('\n');
  1105. X            lcount = 0;
  1106. X        }
  1107. X    }
  1108. X    if (lcount > 0)
  1109. X    {
  1110. X        printf ("\n%s",Contstr);
  1111. X        getnoctl ();
  1112. X    }
  1113. X}
  1114. X
  1115. X/*
  1116. X    h_print prints a character and a legend for a help menu.
  1117. X*/
  1118. Xh_print(c,s)
  1119. Xchar c,*s;
  1120. X{
  1121. X    if (strlen(s) > (C_allow - 14))
  1122. X        s [C_allow - 14] = '\0';
  1123. X    if (c > ' ' && c != '\177')
  1124. X        printf ("     %c - %s\n",c,s);
  1125. X    else
  1126. X    {
  1127. X        switch (c)
  1128. X        {
  1129. X        case '\177':
  1130. X            printf ("  <delete> - %s\n",s);  
  1131. X            break;
  1132. X        case '\040':
  1133. X            printf ("   <space> - %s\n",s);  
  1134. X            break;
  1135. X        case '\033':
  1136. X            printf ("  <escape> - %s\n",s);  
  1137. X            break;
  1138. X        case '\n':
  1139. X            printf ("  <return> - %s\n",s);  
  1140. X            break;
  1141. X        case '\t':
  1142. X            printf ("     <tab> - %s\n",s);  
  1143. X            break;
  1144. X        case '\b':
  1145. X            printf (" <back sp> - %s\n",s);  
  1146. X            break;
  1147. X        case '\f':
  1148. X            printf ("<formfeed> - %s\n",s);  
  1149. X            break;
  1150. X        case '\07':
  1151. X            printf ("    <bell> - %s\n",s);  
  1152. X            break;
  1153. X        case '\0':
  1154. X            printf ("    <null> - %s\n",s);  
  1155. X            break;
  1156. X        default:
  1157. X            if (c < '\033')
  1158. X            {
  1159. X                c += 'a' - 1;
  1160. X                printf(" control-%c - %s\n",c,s);
  1161. X            }
  1162. X            else
  1163. X                printf("       %c0%o - %s\n",'\\',(int) c,s);
  1164. X            break;
  1165. X        }
  1166. X    }
  1167. X}
  1168. X
  1169. Xtot_list (rec,hirec)
  1170. Xint *rec;
  1171. Xint *hirec;
  1172. X{
  1173. X    int i,max,len;
  1174. X    char c;
  1175. X    char ff[MAX_C+1];
  1176. X
  1177. X    term_set (ERASE);
  1178. X
  1179. X    for (max=i=0; i < Ncount; ++i)
  1180. X    {
  1181. X        if ((Newsorder[i])->pages == 0)
  1182. X            continue;
  1183. X        if ((len = strlen((Newsorder[i])->nd_name)) > max)
  1184. X            max = len;
  1185. X    }
  1186. X
  1187. X    sprintf (ff,"%%4d %%%ds: %%3d new %%3d updated\n",max);
  1188. X
  1189. X    for (len=i=0; i < Ncount; ++i)
  1190. X    {
  1191. X        if ((Newsorder[i])->pages == 0)
  1192. X            continue;
  1193. X        printf (ff, i, (Newsorder[i])->nd_name,
  1194. X                (Newsorder[i])->art - (Newsorder[i])->orgrd,
  1195. X                (Newsorder[i])->rdnum - (Newsorder[i])->orgrd);
  1196. X        ++len;
  1197. X        if (len == L_allow && i < (Ncount-1))
  1198. X        {
  1199. X            printf("\nr - return, n - new group, other to continue ... ");
  1200. X            if ((c = getnoctl()) == 'r' || c == 'n')
  1201. X                break;
  1202. X            printf ("\n\n");
  1203. X            len = 0;
  1204. X        }
  1205. X    }
  1206. X    if (i >= Ncount)
  1207. X    {
  1208. X        printf("n - new group, other to return ... ");
  1209. X        c = getnoctl();
  1210. X    }
  1211. X    if (c == 'n')
  1212. X    {
  1213. X        printf("\n");
  1214. X        user_str(ff,"Newsgroup number ? ",0);
  1215. X        i = atoi(ff);
  1216. X        if (i < 0)
  1217. X            i = 0;
  1218. X        if (i >= Ncount)
  1219. X            i = Ncount-1;
  1220. X        find_page((Newsorder[i])->pnum);
  1221. X        *rec = RECBIAS;
  1222. X        *hirec = Page.h.artnum + RECBIAS;
  1223. X    }
  1224. X}
  1225. @//E*O*F vn.c//
  1226. if test 25993 -ne "`wc -c <'vn.c'`"; then
  1227.     echo shar: error transmitting "'vn.c'" '(should have been 25993 characters)'
  1228. fi
  1229. fi # end of overwriting check
  1230. echo shar: extracting "'vn.man'" '(19673 characters)'
  1231. if test -f 'vn.man' ; then 
  1232.   echo shar: will not over-write existing file "'vn.man'"
  1233. else
  1234. sed 's/^X//' >vn.man <<'@//E*O*F vn.man//'
  1235. X.TH VN 1 2/1/85
  1236. X.UC
  1237. X.SH NAME
  1238. Xvn - visual news reader
  1239. X.SH SYNOPSIS
  1240. X.I vn
  1241. X.SH DESCRIPTION
  1242. X.I Vn
  1243. Xis a news reader which uses the same 
  1244. X.B .newsrc
  1245. Xfile as
  1246. X.I readnews
  1247. X(1), but displays and interacts differently.  It is aimed at allowing
  1248. Xyou to rapidly scan a large number of newsgroups, looking for something
  1249. Xyou want to read.  The major premise is that you will be interested in a
  1250. Xsmall number of articles, but will be interested in keeping tabs on a large
  1251. Xnumber of newsgroups which may contain something interesting from time to time.
  1252. XIt also has the ability to unpackage digests.
  1253. X.sp
  1254. X.I Vn
  1255. Xsupports the -n, -x and -t options of
  1256. X.I readnews
  1257. X(newsgroup, read all articles, and title).  In addition, there
  1258. Xis a -w (writer) option which works like -t, but is a search string to
  1259. Xapply to the "From" header line rather than the subject.  In the -n, -t
  1260. Xand -w options, a leading ! on the string is taken to mean negation.
  1261. XThe rest of the string is a regular expression for the -w and -t options.
  1262. X.sp
  1263. XFor example:
  1264. X.sp
  1265. X-n net.dogs -w !fred -t [Bb]eagle
  1266. X.sp
  1267. XFor articles in net.dogs about beagles written by somebody other
  1268. Xthan fred.  Multiple -w -t options are treated as follows:
  1269. X.in +5
  1270. X.sp
  1271. XIf the article satisfies any of the negations, you won't see it,
  1272. Xregardless of the non-negated options.
  1273. X.sp
  1274. XMultiple -w options are logically "or'ed", as are multiple -t's.
  1275. X.sp
  1276. XIf both -w and -t are present, the article is seen only if it satisfies
  1277. Xat least one of the -w's and at least one of the -t's, ie. the results of the
  1278. Xlogical "or's" of the -t's and -w's are logically "anded".
  1279. X.sp
  1280. X.in -5
  1281. XThe -n options allow the "all" convention, replacing ".all" by
  1282. X".*" before using the regular expression calls.  -n options are processed
  1283. Xin order given, so that subsequent more specific -n's may partially
  1284. Xundo the effect of previous "alls".  Note that the -n option
  1285. Xtreatment is slightly different than the
  1286. X.I readnews
  1287. Xtreatment which says that "foo" implies "foo.all".
  1288. X.I Vn
  1289. Xaccepts this incompatibility to allow you an easier way of saying JUST "foo"
  1290. Xwithout any of its subgroups.
  1291. X.sp
  1292. XOptions may be given on the command line, in which case they will
  1293. Xsupersede those given in the
  1294. X.B .newsrc
  1295. Xfile.  For command line -n options, the "!" unsubscriptions in
  1296. X.B .newsrc
  1297. Xare also ignored.  This allows you to override all subscription information
  1298. Xby command line specification.  If you use an -S option on the command line,
  1299. Xthe "!" unsubscriptions will still be used.  -S is meaningless in the
  1300. X.B .newsrc
  1301. Xfile.
  1302. X.sp
  1303. XThere are three more options specific to
  1304. X.I vn:
  1305. Xthe -% and -U.  The -% option initially gives you the results of a "%"
  1306. Xcommand, rather than the page for the first newsgroup (see below).
  1307. XThis allows you to see what newsgroups are available before viewing any.
  1308. XThe -U option says that when your
  1309. X.B .newsrc
  1310. Xfile is updated via answering "yes" to the update query on
  1311. Xexit or using control-W, newsgroups marked with "!" are to be updated too.
  1312. XNormally, these groups are left alone, ie. updated only to the number that
  1313. Xwas already in your
  1314. X.B .newsrc,
  1315. Xor the lowest article number still around.
  1316. XYou may get flooded should you decide to resubscribe.
  1317. XIf you don't like this treatment, use -U.  Then, control-W and "yes" to
  1318. Xthe update on exit will update your unsubscribed newsgroups to the most
  1319. Xrecent article.
  1320. X.sp
  1321. XWhen
  1322. X.I vn
  1323. Xis invoked,
  1324. Xthere will be a pause (with an explanatory "reading" message and
  1325. Xa series of newsgroups) while vn reads the news.  The newsgroups listed
  1326. Xare ones articles are actually being found in.
  1327. XThe length of the pause depends
  1328. Xon how much news there is.  If there is a lot,
  1329. Xit may take a long time to get through the reading phase.
  1330. X.sp
  1331. XOnce the reading phase is over, interaction is rapid.
  1332. XIf
  1333. X.I vn
  1334. Xis backgrounded, it suppresses the "reading" output, so
  1335. Xthat it will not halt on tty output until it is ready to begin showing
  1336. Xarticles.
  1337. X.sp
  1338. X.I Vn
  1339. Xmay show you a list of newsgroups which were not mentioned in the
  1340. X.B .newsrc
  1341. Xfile.  Records for these newsgroups will be added, whether
  1342. Xthey were scanned for articles or not.  The first time
  1343. X.I vn
  1344. Xis used, the list may be quite long and scroll off the screen.
  1345. XThereafter, there should only be a list when new newsgroups are
  1346. Xcreated.  This display serves to let you know of their existence,
  1347. Xor of something happening to your
  1348. X.B .newsrc
  1349. Xfile.
  1350. X.sp
  1351. XThe basic display is a "page" which shows a newsgroup and a list of
  1352. Xtitles, number of
  1353. Xlines, and authors for new articles.
  1354. XArticles which have been updated in the
  1355. X.B .newsrc
  1356. Xfile  are flagged with an underscore preceding the article number.
  1357. XYou also have the ability to "mark" articles for the duration of a session,
  1358. Xshown with an asterisk (col. 1 and 2 are reserved for asterisk and
  1359. Xunderscore respectively - 
  1360. Xin normal usage they will be blank, so that the casual user will probably
  1361. Xbe unaware of their use until marking and updating are invoked)
  1362. X.sp
  1363. XThere is a help menu to go with this page.
  1364. XYou may read articles, save them, send them to the printer, either by cursor
  1365. Xposition, the whole page, or in specified sets.  Sets are specified either
  1366. Xas a set of article numbers, a regular expression to match the subject /
  1367. Xauthor / number of lines data on, or an asterisk to indicate the choice
  1368. Xof a set of previously marked articles.  Any of these methods also
  1369. Xaccept a leading "!" to indicate negation.
  1370. X.sp
  1371. XBy default, when you read articles only a couple of the dozen or so
  1372. Xheader lines are
  1373. Xshown.  There is an option to allow you to see all the
  1374. Xheader lines when you read articles.  The command controlling this toggles
  1375. Xbetween the two states.
  1376. X.sp
  1377. XA similar toggle is used to support ROT13.
  1378. X.sp
  1379. X.I Vn
  1380. Xis capable of manipulating digests.  The "d" command unpacks a digest,
  1381. Xand presents you with a page showing the unpacked articles, which can
  1382. Xbe accessed as for articles on normal newsgroup pages.
  1383. XWhen you leave the digest page(s), you reenter the normal flow of newsgroups.
  1384. XDigests can also be read as normal articles, of course.
  1385. X.sp
  1386. XOrder of pages is determined by
  1387. Xorder of groups in
  1388. X.B .newsrc.
  1389. XNewsgroups which are not
  1390. Xmentioned in
  1391. X.B .newsrc
  1392. Xwill be added, as mentioned previously, and tacked onto the end.
  1393. XLines corresponding to non-existent newsgroups will be deleted.
  1394. XYou will probably want to run
  1395. X.I vn
  1396. Xonce, then edit
  1397. X.B .newsrc
  1398. Xto the desired order of presentation.
  1399. X.sp
  1400. XUpdating the data for
  1401. X.B .newsrc
  1402. Xis under user control.  If you do
  1403. Xno "W", "w", "^w", o or O commands, no updating takes place, and you'll see the
  1404. Xarticles again the next time you read news.
  1405. XIf you quit without updating, you will be prompted to make sure you
  1406. Xdon't want to do so.
  1407. X.sp
  1408. XNote that "updating what you've seen" to
  1409. X.I vn
  1410. Xmeans that you've seen the page presentation, not that you've read the
  1411. Xarticle.  This is consistent with the overall assumption that you don't
  1412. Xwant to read most of what you are presented with.
  1413. X.sp
  1414. XBreaks result in a "really quit?" query, so you can recover from noisy
  1415. Xlines and prompts for commands you didn't really mean.  If you answer no,
  1416. Xyou are simply jumped back to the page.  Breaks while in the midst of scrolling
  1417. Xout an article you are reading jump you to the end of the article to stop
  1418. Xthe output.
  1419. X.sp
  1420. XCommands are single character (no return key required), except that
  1421. Xthey may be preceded with numeric characters, which may have
  1422. Xsome effect on their actions.  Commands which require further input
  1423. Xcause prompts for the information, this input being
  1424. Xterminated by return.  For prompted input, the erase and kill keys
  1425. Xwork.
  1426. X.sp
  1427. X.ce 1
  1428. XCommand Menu For Page:
  1429. X.sp
  1430. X.nf
  1431. X[...] = effect of optional number preceding command
  1432. Xpipes are specified by filenames beginning with |
  1433. Xarticles specified as a list of numbers, title search string, or
  1434. X    * to specify marked articles.  ! may be used to negate any
  1435. X
  1436. X     q - quit
  1437. X     k - (or up arrow) move up [number of lines]
  1438. X     j - (or down arrow) move down [number of lines]
  1439. X <back sp> - (or left arrow) previous page [number of pages]
  1440. X  <return> - (or right arrow) next page [number of pages]
  1441. X     d - unpack digest
  1442. X     r - read article [number of articles]
  1443. X   <space> - read article (alternate 'r')
  1444. X     R - read all articles on page
  1445. X control-r - specify articles to read
  1446. X     s - save or pipe article [number of articles]
  1447. X     S - save or pipe all articles on page
  1448. X control-s - specify articles to save
  1449. X control-t - specify articles to save (alternate ctl-s)
  1450. X     p - print article [number of articles]
  1451. X     P - print all article on page
  1452. X control-p - specify articles to print
  1453. X     w - update .newsrc status to cursor
  1454. X     W - update .newsrc status for whole newsgroup
  1455. X control-w - update .newsrc status for all pages displayed
  1456. X     o - recover original .newsrc status for newsgroup
  1457. X     O - recover all original .newsrc status
  1458. X     # - display count of groups and pages - shown and total
  1459. X     % - list newsgroups with new article, updated counts
  1460. X     n - specify newsgroup to display and/or resubscribe to
  1461. X     u - unsubscribe from group
  1462. X     x - mark/unmark article [number of articles]
  1463. X     * - mark/unmark article [number of articles]
  1464. X     X - erase marks on articles
  1465. X     h - toggle flag for display of headers when reading
  1466. X     z - toggle rotation for reading
  1467. X<formfeed> - redraw screen
  1468. X     ! - escape to UNIX to execute a command
  1469. X     ? - show this help menu
  1470. X.fi
  1471. X.sp
  1472. XWhen you read articles, there is another help menu, for advancing through
  1473. Xthe articles, replying, posting followups, and saving the
  1474. Xarticles.  Breaks may be used to
  1475. Xstop the output of an article if you decide that you didn't really
  1476. Xwant to read it.  You can jump from the reading portion back to either
  1477. Xpage you came from or the NEXT page.
  1478. X.sp
  1479. XFor replying and posting followups, you will be thrown into an editor
  1480. Xto create the reply or article.
  1481. XThe article will be included in the file you are editing, marked with
  1482. X"> "'s for excerpting in your reply or followup.  After you exit the
  1483. Xeditor, you are prompted to make sure you still want to post or reply,
  1484. Xso you can abort.
  1485. X.sp
  1486. XFor followups, your article is appended to "author_copy" for future
  1487. Xreference.
  1488. X.sp
  1489. XHeader lines for the mailer / news poster are present in the file
  1490. Xyou are editing to allow you to modify them.  Remember to leave a blank
  1491. Xline between the header lines and your text.  It may be OK if you
  1492. Xdon't, but why tempt fate.
  1493. X.sp
  1494. XThe editor is determined by your EDITOR variable, as for
  1495. X.I postnews.
  1496. XIf EDITOR is not set, you get
  1497. X.I vi,
  1498. Xor the default determined at your site.
  1499. X.sp
  1500. X.ce 1
  1501. XReading menu:
  1502. X.sp
  1503. X.nf
  1504. X         n - next article, if any
  1505. X         q - quit reading articles, if any more to read
  1506. X         Q - quit reading, and turn to next page of articles
  1507. X         r - rewind article to beginning
  1508. X  <return> - next line
  1509. X         / - search for a pattern in the article
  1510. X         m - send mail to author of article
  1511. X         f - post followup to article
  1512. X         s - save article in a file
  1513. X         p - send article to the printer
  1514. X         ? - see this help menu
  1515. X     z - toggle rotation flag
  1516. X     h - toggle header suppression flag
  1517. X
  1518. X anything else to continue normal reading
  1519. X.fi
  1520. X.sp
  1521. XIf you don't like the choice of command keys, you
  1522. Xmay change them (default choices - basic control in article
  1523. Xreader is ala "more" of course, the "j" and "k" on the page presentation
  1524. Xare "vi" convention, other page commands are somewhat "readnews" compatible).
  1525. XIf you have a file named
  1526. X.B .vnkey
  1527. Xin your home directory this file will be read in order to obtain keystroke
  1528. Xtranslation.  The format is simple:
  1529. X.sp
  1530. XEach line begins with R or P indicating translation for the reader interaction,
  1531. Xor the page interaction (r and p accepted also).  Following the R or P is
  1532. Xa character, followed by an "=", followed by another character.  The character
  1533. Xon the left hand side of the equals sign is what you wish to input, and the
  1534. Xcharacter on the right hand side of the equals sign is what you wish to
  1535. Xtranslate it to.  No embedded spaces.
  1536. XLines not beginining with the proper characters are simply
  1537. Xignored, as are characters following the translated character.  Eg:
  1538. X.sp
  1539. X.in +5
  1540. XPd=j
  1541. X.br
  1542. XPu=k
  1543. X.in -5
  1544. X.sp
  1545. Xuses "u" and "d" instead of "j" and "k" on the page layout (presumably,
  1546. Xyou are also going to translate something else to "u" and "d" for the
  1547. Xunsubscribe and digest commands).  If you translate keys, it is up to you
  1548. Xto see that all commands can still be reached, and that former command keys
  1549. Xwhich are no longer used are mapped to something meaningless.  In particular,
  1550. Xyou are going to have difficulties if you make it impossible to input "q".  The
  1551. Xhelp menus will show the "new" keys, and bad mappings should show up as
  1552. Xmultiple definitions for the same key, or alternate mappings not showing
  1553. Xup on the help menu.
  1554. X.sp
  1555. XMapping the "=" key via "==" works.  Any keys not mentioned in the file
  1556. Xare translated to themselves.
  1557. X.sp
  1558. XControl keys are given as DECIMAL numbers with no backslashes or anything.
  1559. XThe decimal number is the ASCII code for the character, eg:
  1560. X.sp
  1561. X.in +5
  1562. XP24=12
  1563. X.br
  1564. XP12=?
  1565. X.in -5
  1566. Xuses "control-x" for the "control-l (formfeed)" refresh key, and maps the
  1567. Xcontrol-l to a "?".  BTW, mapping all undefined keys to "?" will mean that you
  1568. Xautomatically get the help display for any illegal key, should you wish for
  1569. Xsuch a thing.  The LAST one mapped will determine what key is given in
  1570. Xthe "? for help" lines, and the help display itself.
  1571. XRemembering that control-A through
  1572. Xcontrol-Z are ASCII codes 1 through 26 and delete = 127 may keep you from
  1573. Xhaving to consult an ASCII table.  Remember also that some controls, such
  1574. Xas control- C, Z, S or Q may be caught by the operating system for signal
  1575. Xgeneration or terminal control, and are thus unavailable.
  1576. X.sp
  1577. XBecause of arrow keys and the ability to prefix commands with counts,
  1578. Xnumeric characters and the escape key may not be used for page commands.
  1579. XAttempts to use them will simply do nothing.
  1580. X.sp
  1581. XControl keys are not available for the reader, except for newline,
  1582. Xbackspace, and tab.  The reason controls are filtered here has to do
  1583. Xwith nasty problems involving terminal mode switches on some systems,
  1584. Xspecifically a UTS frontend early versions were being used on.
  1585. X.sp
  1586. XIn either interaction, "return" and "linefeed" are mapped to the "newline"
  1587. Xcharacter at a level below the translation.  If you don't know the
  1588. XASCII for the "newline" char, it is recommended that you map both
  1589. XASCII 10 and 13 if you wish to map "return" to something.
  1590. X.SH FILES
  1591. X.TP 24
  1592. X/usr/tmp/*
  1593. XOne temporary file created by
  1594. X.I tmpnam
  1595. X(3), and immediately unlinked,
  1596. Xremains open in update mode for duration of session.
  1597. XDisk space freed by system close of file descriptor at exit.
  1598. XCan be large, as this file contains the "page" displays.
  1599. XTemporary files also created by
  1600. X.I tmpnam
  1601. X(3) for mailing replies, posting followups and creating digest "articles".
  1602. X.TP 24
  1603. X(login directory)/.newsrc
  1604. Xnews status file.  Updated following session.  See NEWSRC environment variable.
  1605. X.TP 24
  1606. X(login directory)/author_copy
  1607. XA copy of all articles posted using the followup command will be appended
  1608. Xto this file in /bin/mail format.  See CCFILE environment variable.
  1609. X.TP 24
  1610. X(login directory)/.vnkey
  1611. XKeystroke mapping file for changing command characters.
  1612. X.TP 24
  1613. X(login directory)/*.vnXXXXXX
  1614. XOne temporary file created by
  1615. X.I tmpnam
  1616. X(3) while updating the .newsrc file.  If the update fails, you are informed,
  1617. Xand this file
  1618. Xmay be used to recover the last update.  Unlinked following successful update.
  1619. X.TP 24
  1620. X(spool directory)/*
  1621. Xspooling directories containing articles.
  1622. X.TP 24
  1623. X/usr/lib/news/active
  1624. Xactive newsgroup list.
  1625. X.SH "ENVIRONMENT VARIABLES"
  1626. X.TP 24
  1627. XPS1
  1628. Xused to present prompt string for command on unix escape.
  1629. Xdefaults to "$ "
  1630. X.TP 24
  1631. XEDITOR
  1632. Xeditor used for mailing replies and posting followups.
  1633. Xdefaults to "ed".
  1634. X.TP 24
  1635. XPOSTER
  1636. Xposting program for followups.  defaults to "inews -h".
  1637. X.TP 24
  1638. XMAILER
  1639. Xused when mailing replies.  defaults to "sendmail -t".
  1640. X.TP 24
  1641. XPRINTER
  1642. Xprogram used with the print commands for sending articles to
  1643. Xthe printer.  defaults to "lpr".
  1644. X.TP 24
  1645. XNEWSRC
  1646. Xif set, can be used to override the choice of ".newsrc" as the
  1647. Xname for the status file.  Name will still be used relative to
  1648. Xthe login directory, unless it begins with "/".
  1649. X.TP 24
  1650. XCCFILE
  1651. Xif set, overrides the choice of "author_copy" as the name of the
  1652. Xfile to CC all articles posted with the followup command.  Name
  1653. Xwill still be used relative to the login directory, unless it begins
  1654. Xwith "/".
  1655. X.TP 24
  1656. XVNKEY
  1657. Xif set, overrides the choice of ".vnkey" as the name of the
  1658. Xfile to map keys from.  Name
  1659. Xwill still be used relative to the login directory, unless it begins
  1660. Xwith "/".
  1661. X.SH DIAGNOSTICS
  1662. Xuser error messages.  self explanatory.
  1663. X.SH AUTHOR
  1664. XR. L. McQueer
  1665. X.SH BUGS
  1666. XNote that
  1667. X.I readnews
  1668. Xwill rearrange the order of
  1669. X.B .newsrc.
  1670. XIf you
  1671. Xinterleave use of it with
  1672. X.I vn,
  1673. Xorder selection gets hosed.
  1674. X.sp
  1675. XIf you've really taken advantage of the ability of readnews to skip
  1676. Xarticles in the middle of the spooling numbers, be warned that
  1677. X.I vn
  1678. Xdoesn't have it, and will
  1679. Xassume you've read the articles in the middle.
  1680. X.sp
  1681. XIf the
  1682. X.B .newsrc
  1683. Xfile indicates that you've read articles in a newsgroup with a higher
  1684. Xnumber than the current spooling number for that newsgroup,
  1685. X.I vn
  1686. Xwill show you the entire newsgroup.  This is intended for recovery in
  1687. Xcases where article spooling has been reset, or to avoid missing articles
  1688. Xbecause you just changed machines and didn't bother to edit your
  1689. X.B .newsrc
  1690. Xfile.  Rather than miss stuff, you'll see some old stuff again.
  1691. X.sp
  1692. XSometimes a "break" during reading an article will not only halt the
  1693. Xarticle but suppress the prompt.  A command character will work anyway.
  1694. X.sp
  1695. XIf a prompt to be displayed on the dialogue line
  1696. Xcontains non-printing sequences, stuff on the
  1697. Xline may not get erased when you are prompted, because
  1698. X.I vn
  1699. Xthinks the string is long enough to overprint its current contents.
  1700. XThis usually comes up when you have escape sequences in your UNIX
  1701. Xprompt, and do a "!" command.
  1702. XThe "overprint" check is made to save a clear-line sequence (kludged in
  1703. Xby overprinting to the end with blanks if the terminal doesn't
  1704. Xhave one - annoying at 1200 baud).
  1705. X.sp
  1706. XOutput during the reading phase which was suppressed by backgrounding
  1707. X.I vn
  1708. Xdoes not get started by foregrounding it again without doing a
  1709. Xcontrol-z and a second foreground (it doesn't figure out its background /
  1710. Xforeground status on each output - only on startup and while handling
  1711. Xthe SIGTSTP signal).  Actually, this results in a method for having
  1712. X.I vn
  1713. Xdo its reading phase silently in the foreground without redirecting
  1714. Xoutput, should such a thing be desired.
  1715. X.sp
  1716. XVery many -w or -t options cause SLOW reading phases.  It is reccomended
  1717. Xthat these be used only when reading a few specific groups.
  1718. X.sp
  1719. XDigest extraction will split a single article into several if it contains
  1720. Xembedded ---- lines, the normal separator between articles in digests.
  1721. XThey will all have identical titles.
  1722. XDigest extraction may not work with human built digests which don't
  1723. Xuse the expected syntax for joining articles.  mod.computers.ibm-pc
  1724. Xand mod.computers.mac were used as models for the feature.
  1725. X.sp
  1726. XThe data given by the % command represents the difference between the
  1727. Xlast article number you've updated to in a newsgroup and the high
  1728. Xarticle number.  This may be significantly greater than the number of
  1729. Xactual articles for a newsgroup you haven't been reading, and for
  1730. Xnewsgroups that have had a lot of articles filtered out of them using
  1731. Xthe -w and -t options.  The numbers given for menu selection in the
  1732. X % command are the order numbers from the .newsrc, and have gaps for
  1733. Xunsubscribed newsgroups.
  1734. X.sp
  1735. XThe key mapping capability doesn't handle function keys.  Because of the
  1736. Xuse of controls as commands, terminals whose arrow keys echo something
  1737. Xother than a sequence beginning with escape can't use arrow keys.  For
  1738. Xthese terminals, a warning message is printed during the reading phase.
  1739. @//E*O*F vn.man//
  1740. if test 19673 -ne "`wc -c <'vn.man'`"; then
  1741.     echo shar: error transmitting "'vn.man'" '(should have been 19673 characters)'
  1742. fi
  1743. fi # end of overwriting check
  1744. echo shar: "End of archive 3 (of 3)."
  1745. cp /dev/null ark3isdone
  1746. DONE=true
  1747. for I in 1 2 3; do
  1748.     if test -! f ark${I}isdone; then
  1749.         echo "You still need to run archive ${I}."
  1750.         DONE=false
  1751.     fi
  1752. done
  1753. case $DONE in
  1754.     true)
  1755.         echo "You have run all 3 archives."
  1756.         echo 'Now read the README'
  1757.         ;;
  1758. esac
  1759. ##  End of shell archive.
  1760. exit 0
  1761.